#include <bits/stdc++.h>

using namespace std;

namespace m_std
{
    template <typename T>
    class auto_ptr
    {
        // RAII思想
        //  auto_ptr(const &T *ptr)
        auto_ptr(T *ptr = nullptr)
            : _ptr(ptr)
        {
        }
        ~auto_ptr()
        {
            if (_ptr)
            {
                delete _ptr;
                cout << "~auto_ptr()" << endl;
            }
        }
        //像指针一样
        T *operator*()
        {
            return this;
        }
        T &operator->()
        {
            return *this;
        }
        //拷贝和赋值 -> 管理权转移
        auto_ptr(auto_ptr<T> &ptr)
            : _ptr(ptr._ptr)
        {
            ptr._ptr = nullptr; //原智能指针会被悬空
        }
        auto_ptr<T> &operator=(auto_ptr<T> &ptr)
        {
            //如果是自己给自己赋值(两个智能指针管理同一个资源), 则直接返回即可
            if (ptr->_ptr == _ptr)
            {
                return *this;
            }
            //如果不是自己给自己赋值, 则接管原资源, 原智能指针不再管理
            if (_ptr)
            {
                //如果当前智能指针管理着资源,则释放当前资源, 接管新资源
                delete _ptr;
                cout << "operator=(auto_ptr<T>&ptr) delete" << endl;
            }
            _ptr = ptr._ptr;    //接管资源
            ptr._ptr = nullptr; //原智能指针不再管理
            return *this;
        }

    private:
        T *_ptr;
    };
    template <class T>
    class unique_ptr
    {
        // RAII思想
        unique_ptr(T *ptr = nullptr)
            : _ptr(ptr)
        {
        }
        ~unique_ptr()
        {
            if (_ptr)
            {
                delete _ptr;
                cout << "~unique_ptr()" << endl;
            }
        }
        //像指针一样
        T *operator*()
        {
            return this;
        }
        T &operator->()
        {
            return *this;
        }
        //拷贝和赋值
        unique_ptr(unique_ptr<T> &ptr) = delete;
        unique_ptr<T> &operator=(unique_ptr<T> &ptr) = delete;

    private:
        T *_ptr;
    };
    template <class T>
    class shared_ptr
    {
        // RAII思想
        shared_ptr(T *ptr = nullptr)
            : _ptr(ptr)
        {
        }
        void release()
        {
            if (--(*_count) == 0)
            {
                cout << "Delete:" << _ptr << endl;
                delete _ptr;
                delete _count;
            }
        }
        ~shared_ptr(){
            release();
        }
        //拷贝和赋值
        shared_ptr(shared_ptr<T> &ptr)
            : _ptr(ptr._ptr), _count(ptr._count)
        {
            ++(*_count);
        }
        shared_ptr<T> &operator=(shared_ptr<T> &ptr)
        {
            //自己给自己赋值则直接return
            if (ptr._ptr == _ptr)
            {
                return *this;
            }
            release();
            _ptr = ptr._ptr;
            _count = ptr._count;
            *(_count)++;
            return *this;
        }
        //像指针一样
        T *operator*()
        {
            return this;
        }
        T &operator->()
        {
            return *this;
        }

    private:
        T *_ptr;
        int *_count;
    };
}